package config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.util.Properties;

import exception.InvalidConfigException;

/**
 * Manages a set of configurations of the application
 * @author Mauri
 */
public class ConfigManager {
	private static String CONFIG_FILE = "src/config/config.properties";
	private static Properties properties;
	private static FileInputStream fis;
	private static FileOutputStream fos;
	private static String basePath = null;
	private static boolean isOpen = false;

	public static Integer getIntConfig(String attribute) throws InvalidConfigException {
		Integer value = -1;
		try {
			if (openConfig())
				value = Integer.parseInt(properties.getProperty(attribute));
		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
			throw new InvalidConfigException("Config file not found: " + ex.getMessage());
		} catch (IOException ex) {
			ex.printStackTrace();
			throw new InvalidConfigException("IO issue: " + ex.getMessage());
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new InvalidConfigException("Invalid attribute '" + attribute + "': " + ex.getMessage());
		}
		return value;
	}

	public static String getStringConfig(String attribute) throws InvalidConfigException {
		String value = "";
		try {
			if (openConfig())
				value = properties.getProperty(attribute);
		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
			throw new InvalidConfigException("Config file not found: " + ex.getMessage());
		} catch (IOException ex) {
			ex.printStackTrace();
			throw new InvalidConfigException("IO issue: " + ex.getMessage());
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new InvalidConfigException("Invalid attribute '" + attribute + "': " + ex.getMessage());
		}
		return value;
	}

	public static Double getDoubleConfig(String attribute) throws InvalidConfigException {
		Double value = 0.0;
		try {
			if (openConfig())
				value = Double.parseDouble(properties.getProperty(attribute));
		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
			throw new InvalidConfigException("Config file not found: " + ex.getMessage());
		} catch (IOException ex) {
			ex.printStackTrace();
			throw new InvalidConfigException("IO issue: " + ex.getMessage());
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new InvalidConfigException("Invalid attribute '" + attribute + "': " + ex.getMessage());
		}
		return value;
	}

	public static Boolean getBooleanConfig(String attribute) throws InvalidConfigException {
		Boolean value = null;
		try {
			if (openConfig())
				value = Boolean.valueOf(properties.getProperty(attribute));
		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
			throw new InvalidConfigException("Config file not found: " + ex.getMessage());
		} catch (IOException ex) {
			ex.printStackTrace();
			throw new InvalidConfigException("IO issue: " + ex.getMessage());
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new InvalidConfigException("Invalid attribute '" + attribute + "': " + ex.getMessage());
		}
		return value;
	}

	private static boolean openConfig() throws Exception {
		if (isOpen) {
			return true;
		}
		try {
			String fileName = null;
			if (basePath != null) {
				fileName = basePath + CONFIG_FILE.replace("src/", "");
			}
			else {
				fileName = CONFIG_FILE;
			}
			fis = new FileInputStream(new File(new URI(fileName)));
			properties = new Properties();
			properties.load(fis);
			fis.close();
			isOpen = true;
		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
			System.out.println("Config file not found: " + ex.getMessage());
			throw ex;
		} catch (Exception ex) {
			ex.printStackTrace();
			System.out.println("Failed to load the properties: " + ex.getMessage());
			throw ex;
		}
		return isOpen;
	}

	public static boolean writeConfig(String attribute, String value) throws Exception {
		boolean flag = true;
		try {
			openConfig();
		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
			flag = false;
		} catch (IOException ex) {
			ex.printStackTrace();
			flag = false;
		}
		properties.setProperty(attribute, value);
		try {
			String fileName = null;
			if (basePath != null) {
				fileName = basePath + CONFIG_FILE.replace("src/", "");
			}
			else {
				fileName = CONFIG_FILE;
			}
			fos = new FileOutputStream(new File(new URI(fileName)));
			properties.store(fos, null);
			fos.close();
			flag = true;
		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
			System.out.println("Config file not found: " + ex.getMessage());
			throw ex;
		} catch (Exception ex) {
			ex.printStackTrace();
			System.out.println("Failed to save properties: " + ex.getMessage());
			throw ex;
		}
		return flag;
	}

	/**
	 * Acceso a basePath
	 * @return valor del atributo basePath
	 */
	public static String getBasePath() {
		return basePath;
	}

	/**
	 * Modificador de basePath
	 * @param basePath nuevo valor del atributo basePath
	 */
	public static void setBasePath(String path) {
		basePath = path;
	}
}
